package com.bougaga.opensource.scheduler.springboot.autoconfigure;

import com.bougaga.opensource.scheduler.core.handler.TaskHandler;
import com.bougaga.opensource.scheduler.core.scheduler.DelayedTaskScheduler;
import com.bougaga.opensource.scheduler.core.task.DelayedTask;
import com.bougaga.opensource.scheduler.core.task.TaskStatus;
import com.bougaga.opensource.scheduler.netty.scheduler.NettyTimeWheelScheduler;
import com.bougaga.opensource.scheduler.redis.storage.RedisTaskStorage;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

/**
 * Bou Scheduler 自动配置类
 * 
 * @author bougaga
 * @since 1.0.0
 */
@Configuration
@ConditionalOnClass(DelayedTaskScheduler.class)
@EnableConfigurationProperties(BouSchedulerProperties.class)
public class BouSchedulerAutoConfiguration {
    
    private static final Logger logger = LoggerFactory.getLogger(BouSchedulerAutoConfiguration.class);
    
    @Bean
    @ConditionalOnMissingBean
    public ObjectMapper objectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        
        // 注册JavaTimeModule以支持Java 8日期时间类型
        JavaTimeModule javaTimeModule = new JavaTimeModule();
        
        // 配置LocalDateTime的序列化和反序列化格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(formatter));
        javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(formatter));
        
        objectMapper.registerModule(javaTimeModule);
        
        logger.info("Configured ObjectMapper with JavaTimeModule support");
        return objectMapper;
    }
    
    @Bean
    @Primary
    @ConditionalOnMissingBean(name = "bouSchedulerRedisTemplate")
    public RedisTemplate<String, String> bouSchedulerRedisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate<String, String> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory);
        
        // 设置序列化器
        StringRedisSerializer stringSerializer = new StringRedisSerializer();
        template.setKeySerializer(stringSerializer);
        template.setValueSerializer(stringSerializer);
        template.setHashKeySerializer(stringSerializer);
        template.setHashValueSerializer(stringSerializer);
        
        template.afterPropertiesSet();
        logger.info("Created BouScheduler RedisTemplate");
        return template;
    }
    
    @Bean
    @ConditionalOnMissingBean
    public RedisTaskStorage redisTaskStorage(RedisTemplate<String, String> bouSchedulerRedisTemplate, ObjectMapper objectMapper) {
        logger.info("Initializing RedisTaskStorage");
        return new RedisTaskStorage(bouSchedulerRedisTemplate, objectMapper);
    }
    
    @Bean
    @ConditionalOnMissingBean
    public NettyTimeWheelScheduler.TaskStorage taskStorage(RedisTaskStorage redisTaskStorage) {
        logger.info("Creating TaskStorage adapter");
        return new RedisTaskStorageAdapter(redisTaskStorage);
    }
    
    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnProperty(prefix = "bou.scheduler", name = "enabled", havingValue = "true", matchIfMissing = true)
    public DelayedTaskScheduler delayedTaskScheduler(
            NettyTimeWheelScheduler.TaskStorage taskStorage,
            List<TaskHandler> taskHandlers) {
        
        logger.info("Initializing NettyTimeWheelScheduler with {} task handlers", taskHandlers.size());
        return new NettyTimeWheelScheduler(taskStorage, taskHandlers);
    }
    
    /**
     * Redis任务存储适配器，实现NettyTimeWheelScheduler.TaskStorage接口
     */
    private static class RedisTaskStorageAdapter implements NettyTimeWheelScheduler.TaskStorage {
        
        private final RedisTaskStorage redisTaskStorage;
        
        public RedisTaskStorageAdapter(RedisTaskStorage redisTaskStorage) {
            this.redisTaskStorage = redisTaskStorage;
        }
        
        @Override
        public boolean saveTask(DelayedTask task) {
            return redisTaskStorage.saveTask(task);
        }
        
        @Override
        public DelayedTask getTask(String taskId) {
            return redisTaskStorage.getTask(taskId);
        }
        
        @Override
        public boolean updateTask(DelayedTask task) {
            return redisTaskStorage.updateTask(task);
        }
        
        @Override
        public boolean deleteTask(String taskId) {
            return redisTaskStorage.deleteTask(taskId);
        }
        
        @Override
        public List<DelayedTask> getAllTasks() {
            return redisTaskStorage.getAllTasks();
        }
        
        @Override
        public List<DelayedTask> getTasksByStatus(TaskStatus status) {
            return redisTaskStorage.getTasksByStatus(status);
        }
        
        @Override
        public List<DelayedTask> getTasksByType(String taskType) {
            return redisTaskStorage.getTasksByType(taskType);
        }
        
        @Override
        public List<DelayedTask> getPendingTasks() {
            return redisTaskStorage.getPendingTasks();
        }
        
        @Override
        public List<DelayedTask> getExpiredTasks() {
            return redisTaskStorage.getExpiredTasks();
        }
        
        @Override
        public long getTaskCountByStatus(TaskStatus status) {
            return redisTaskStorage.getTaskCountByStatus(status);
        }
        
        @Override
        public int cleanupCompletedTasks(LocalDateTime beforeTime) {
            return redisTaskStorage.cleanupCompletedTasks(beforeTime);
        }
    }
    
    /**
     * Web相关配置 - 简化版本
     */
    @Configuration
    @ConditionalOnProperty(prefix = "bou.scheduler.web", name = "enabled", havingValue = "true", matchIfMissing = true)
    @Import(com.bougaga.opensource.scheduler.web.autoconfigure.WebAutoConfiguration.class)
    @ComponentScan(basePackages = "com.bougaga.opensource.scheduler.web")
    public static class WebConfiguration {
        // Web功能现在通过bou-scheduler-web模块的自动配置提供
    }
}
